<?php


namespace App\Repositories;


use App\Models\Product as Model;
use App\Traits\Logs;
use Exception;
use Illuminate\Support\Facades\Redis;
use LTools\Repositories\RepositoryAbstract;

class Product extends RepositoryAbstract
{
    use Logs;

    /**
     * Product constructor.
     * @param Model $model
     */
    public function __construct(Model $model)
    {
        $this->model = $model;
    }

    /**
     * @param array $attributes
     * @param int|null $perPage
     * @param array $columns
     * @param string $pageName
     * @param int|null $page
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     * @author luffyzhao@vip.126.com
     */
    public function paginate(array $attributes, int $perPage = null, array $columns = ['*'], $pageName = 'page', int $page = null)
    {
        return $this->model->with(['customer', 'customs'])->where(
            $attributes
        )->paginate($perPage, $columns, $pageName, $page);
    }

    /**
     * @param array $attributes
     * @return bool|\Illuminate\Database\Eloquent\Model
     * @author luffyzhao@vip.126.com
     */
    public function create(array $attributes = [])
    {
        /** @var Model $model */
        $model = parent::create($attributes);
        $model->customs()->create(
            collect($attributes['customs'])
                ->only(['code', 'name', 'unit', 'unit1', 'unit2', 'qy1', 'qy2', 'country', 'net_weight', 'element'])
                ->toArray() + ['unique' => $this->unique($model->customer->getAttribute('code'))]
        );
        $this->recordLogs($model, '新增产品成功');
        return $model;
    }


    /**
     * @param $id
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model
     * @author luffyzhao@vip.126.com
     */
    public function edit($id)
    {
        return $this->model->with(['customs'])->findOrFail($id);
    }

    /**
     * @param $id
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model
     * @author luffyzhao@vip.126.com
     */
    public function show($id)
    {
        return $this->model->with(['customs', 'customer', 'logs.user', 'orders.order', 'inventory', 'batchs.location'])->findOrFail($id);
    }

    /**
     * @param $id
     * @param array $values
     * @return bool|\Illuminate\Database\Eloquent\Model|void
     * @throws \Throwable
     * @author luffyzhao@vip.126.com
     */
    public function update($id, array $values)
    {
        /** @var Model $model */
        $model = $this->model->newQuery()->where('id', '=', $id)->lockForUpdate()->first();
        if ($model->getAttribute('status') === 0 || $model->getAttribute('status') === 2) {
            $values['status'] = 0;
            $model->fillable(['code', 'customer_id', 'title', 'gross_weight', 'brand', 'status'])->fill($values)->saveOrFail();
            $model->customs()->update(
                collect($values['customs'])->only(['code', 'name', 'unit', 'unit1', 'unit2', 'qy1', 'qy2', 'country', 'net_weight', 'element'])->toArray()
            );
            $this->recordLogs($model, '修改产品成功');

            return $model;
        }
        throw new Exception('产品状态不正确不能修改产品');
    }

    /**
     * @param $id
     * @return Model
     * @throws \Throwable
     * @author luffyzhao@vip.126.com
     */
    public function review($id)
    {
        /** @var Model $model */
        $model = $this->model->newQuery()->where('id', '=', $id)->lockForUpdate()->first();
        if ($model->getAttribute('status') === 1) {
            $model->setAttribute('status', 3);
            $model->saveOrFail();

            /** 添加库存 */
            $model->inventory()->create([
                'customer_id' => $model->getAttribute('customer_id')
            ]);

            $this->recordLogs($model, '产品审核通过');
            return $model;
        }
        throw new Exception('产品状态不正确不能审核产品');
    }

    /**
     * @param $id
     * @return Model
     * @throws \Throwable
     * @author luffyzhao@vip.126.com
     */
    public function confirm($id)
    {
        /** @var Model $model */
        $model = $this->model->newQuery()->where('id', '=', $id)->lockForUpdate()->first();
        if ($model->getAttribute('status') === 0) {
            $model->setAttribute('status', 1);
            $model->saveOrFail();
            $this->recordLogs($model, '确认产品成功');
            return $model;
        }
        throw new Exception('产品状态不正确不能确认产品');
    }

    /**
     * @param $id
     * @param $remark
     * @return Model
     * @throws \Throwable
     * @author luffyzhao@vip.126.com
     */
    public function freeze($id, $remark)
    {
        /** @var Model $model */
        $model = $this->model->newQuery()->where('id', '=', $id)->lockForUpdate()->first();
        if ($model->getAttribute('status') === 3) {
            $model->setAttribute('status', 4);
            $model->saveOrFail();
            $this->recordLogs($model, '冻结产品成功:' . $remark);
            return $model;
        }
        throw new Exception('产品状态不正确不能冻结产品');
    }

    /**
     * @param $id
     * @param $remark
     * @return Model
     * @throws \Throwable
     * @author luffyzhao@vip.126.com
     */
    public function reject($id, $remark)
    {
        /** @var Model $model */
        $model = $this->model->newQuery()->where('id', '=', $id)->lockForUpdate()->first();
        if ($model->getAttribute('status') === 1) {
            $model->setAttribute('status', 2);
            $model->saveOrFail();
            $this->recordLogs($model, '驳回产品成功:' . $remark);
            return $model;
        }
        throw new Exception('产品状态不正确不能驳回产品');
    }

    /**
     * @param $id
     * @return Model
     * @throws \Throwable
     * @author luffyzhao@vip.126.com
     */
    public function thaw($id)
    {
        /** @var Model $model */
        $model = $this->model->newQuery()->where('id', '=', $id)->lockForUpdate()->first();
        if ($model->getAttribute('status') === 4) {
            $model->setAttribute('status', 3);
            $model->saveOrFail();
            $this->recordLogs($model, '解冻产品成功');
            return $model;
        }
        throw new Exception('产品状态不正确不能解冻产品');
    }

    /**
     * @param $id
     * @return bool|mixed
     * @throws Exception
     * @author luffyzhao@vip.126.com
     */
    public function delete($id)
    {
        /** @var Model $model */
        $model = $this->model->newQuery()->where('id', '=', $id)->lockForUpdate()->first();
        if ($model->getAttribute('status') === 0) {
            $model->customs()->delete();
            $model->logs()->delete();
            $model->delete();
            return true;
        }
        throw new Exception('产品状态不正确不能删除产品');
    }

    /**
     * @param $id
     * @return mixed
     * @author luffyzhao@vip.126.com
     */
    public function consumable($id){
        /** @var Model $model */
        $model = $this->find($id);
        $model->setAttribute('consumables', $model->consumable->pluck('id'));
        return $model;
    }

    /**
     * @param $id
     * @param array $values
     * @return Model
     * @author luffyzhao@vip.126.com
     */
    public function postConsumable($id, array $values){
        /** @var Model $model */
        $model = $this->find($id);
        $model->consumable()->sync($values['consumables']??[]);
        return $model;
    }

    /**
     * 料号唯一值
     * @param string $key
     * @return mixed
     * @author luffyzhao@vip.126.com
     */
    protected function unique($key = '')
    {
        $rKey = 'unique:' . $key . ':' . get_class($this);
        $incr = Redis::incr($rKey);
        return $key . str_pad($incr, 6, '0', STR_PAD_LEFT);
    }
}
